unit OneRcd;

interface

uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids, RzGrids, SPComm, ComCtrls, StdCtrls, ExtCtrls, includefile;

type
  TOneRcdfram = class(TFrame)
    RcdStringGrid: TRzStringGrid;
    Serial: TComm;
    showProgress: TPanel;
    progressHint: TLabel;
    ProgBar: TProgressBar;
    OutTimer: TTimer;
    procedure RcdStringGridDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure SerialReceiveData(Sender: TObject; Buffer: Pointer;
      BufferLength: Word);
    procedure OutTimerTimer(Sender: TObject);
  private
    { Private declarations }
    FRcvBuff:string;
    CurrBuff:string;
    FWAITTIME:DWORD;
    FTIMES:WORD;
    FSndLast_Data:string;
    FSndLast_Cmd:String;
    FIsTran:boolean;
    Save2MainDB:integer;
    ContrctArr:Array[0..99] of TContractor;
    RealContrctCount:integer;

    procedure insert2DB(tmpRcd:TRcd);

  public
    { Public declarations }
    function CloseWindow:Boolean;
    function iniSerial:Boolean;
    function startSerial:Boolean;
    function stopSerial:Boolean;
    function saveRcd:Boolean;
    function export2xls:Boolean;
    procedure iniWindows;
    procedure sndData(data:String;cmd:String);
    procedure filteCommData;
    procedure SndPrepare(fstr:string);
    procedure ExSndData(fstr:string);
    procedure SndEnd(fstr:string);
    procedure UpdateRFID(rfid:string);
    procedure UpdatePRODUCT(proName:String);
  end;


implementation

{$R *.dfm}

uses
  Serialset, dbgrid2excel, Crc8, StrUtils, dbmodule, summary;

const
  R_ST_FLG=#02;
  R_ED_FLG=#03;

  SND_PREPARE='ST';
  SND_DATA='DA';
  SND_END='ED';

  RCV_READY='RS';
  RCV_RECEIVED='RD';
  RCV_AGAIN='AG';
  RCV_CLEAR='CL';
  RCV_OK='OK';

  MAX_FILE_SIZE=1024*400;
  MAX_WAIT_TIME=500;
  OVER_TIMES=5;

function ToneRcdfram.CloseWindow:Boolean;
begin
  Result:=True;
  if (Save2MainDB<=(RcdStringGrid.RowCount-2)) then begin
    if IDNO=Application.MessageBox('Records have not been saved, Are you sure to close it?',
                                   'Window Close',MB_YESNO) then
      Result:=False;
  end else begin
     with dbmodulefrm do begin
       dbquery.Active:=False;
       dbtmpqry.Active:=False;
       T_RCD.Active:=False;
       T_EMPLOYEE.Active:=False;
       dbtmpqryEx.Active:=False;
       T_PRODUCT.Active:=False;
     end;
  end;
end;

function TOneRcdfram.export2xls():Boolean;
begin
  Result:=ExportStrGridToExcel([RcdStringGrid]);
end;

procedure TOneRcdfram.UpdateRFID(rfid:string);
var
  tmpcontrct:integer;
  i,j:integer;
  tmprfid,tmpurfid:integer;
begin
  for i:=0 to RealContrctCount-1 do begin
    val(rfid,tmprfid,j);
    val(ContrctArr[i].URFID,tmpurfid,j);
    if (tmpurfid>=tmprfid) then
      break; 
  end;
  tmpcontrct:=ContrctArr[i].ID;
  with dbmodulefrm do begin
    T_EMPLOYEE.Insert;
    T_EMPLOYEE['RFID']:=rfid;
    T_EMPLOYEE['TFNTYPE']:=defTFNtp;
    T_EMPLOYEE['CONTRACTORNAME']:=tmpcontrct;
    try
      T_EMPLOYEE.Post;
    except
      T_EMPLOYEE.Delete;
    end;
  end;
end;

procedure TOneRcdfram.UpdatePRODUCT(proName:String);
begin
  with dbmodulefrm do begin
    T_PRODUCT.Insert;
    T_PRODUCT['PRONAME']:=proName;
    T_PRODUCT['PROALIAS']:=proName;
    try
      T_PRODUCT.Post;
    except
      T_PRODUCT.Delete;
    end;
  end;
end;

procedure TOneRcdfram.insert2DB(tmpRcd:TRcd);
begin
  with dbmodulefrm do begin
    T_RCD.Insert;
    T_RCD['ID']:=tmpRcd.ID;
    T_RCD['SCALEID']:=tmpRcd.ScaleID;
    T_RCD['DATETIME']:=tmpRcd.DateTime;
    T_RCD['RFID']:=tmpRcd.RFID;
    T_RCD['TRAYS']:=tmpRcd.Trays;
    T_RCD['NW']:=tmpRcd.NW;
    T_RCD['GW']:=tmpRcd.GW;
    T_RCD['PRODUCTID']:=tmpRcd.ProductID;
    T_RCD['PENALTY']:=tmpRcd.Penalty;
    T_RCD['GQF']:=tmpRcd.GQF;
    T_RCD['TNW']:=tmpRcd.TNW;
    T_RCD['TGW']:=tmpRcd.TGW;
    try
      T_RCD.Post;
    except
      T_RCD.Delete;
    end;
  end;
end;

procedure TOneRcdfram.iniWindows;
//var
//  I:integer;
begin
  with RcdStringGrid do begin
    Cells[0,0]:='Scale ID';
    Cells[1,0]:='Date';
    Cells[2,0]:='Time';
    Cells[3,0]:='RFID';
    Cells[4,0]:='Trays';
    Cells[5,0]:='NW';
    Cells[6,0]:='GW';
    Cells[7,0]:='Product ID';
    Cells[8,0]:='Penalty';
    Cells[9,0]:='GQF';
   { for i:=1 to 10000 do begin
      Cells[0,i]:='0078';
      Cells[1,i]:='11/08/2009';
      Cells[2,i]:='10:17:21';
      Cells[3,i]:=inttostr((i mod 100)+1);
      Cells[4,i]:='3';
      Cells[5,i]:='48.6';
      Cells[6,i]:='60';
      Cells[7,i]:='Procedure';
      Cells[8,i]:='2';
      Cells[9,i]:='3';
    end;  }
  end;

  if not showGQF then
    RcdStringGrid.ColWidths[9]:=-1
  else
    RcdStringGrid.ColWidths[9]:=100;
  if not showPenalty then
    RcdStringGrid.ColWidths[8]:=-1
  else
    RcdStringGrid.ColWidths[8]:=100;
  with Serial do begin
    CommName:=cmPort;
    BaudRate:=BDRT[cmBdrt];
    Parity:=PRTY[cmPrty];
    ByteSize:=BTSZ[cmBtsz];
    StopBits:=STPBT[cmStpbs];
  end;
  Save2MainDB:=1;
end;

function TOneRcdfram.iniSerial:Boolean;
begin
  Result:=False;
  with TSerialsetfrm.Create(Application) do begin
      comport.ItemIndex:=comport.Items.IndexOf(Serial.CommName);
      comBdrt.ItemIndex:=cmBdrt;
      comParity.ItemIndex:=cmPrty;
      comBtsz.ItemIndex:=cmBtsz;
      comStpBits.ItemIndex:=cmStpbs;
    if Mrok=showmodal then begin
      Serial.StopComm;
      Serial.CommName:=Trim(comPort.Text);
      cmBdrt:=comBdRt.ItemIndex;
      Serial.BaudRate:=BDRT[cmBdrt];
      cmPrty:=comParity.ItemIndex;
      Serial.Parity:=PRTY[cmPrty];
      cmBtsz:=comBtSz.ItemIndex;
      Serial.ByteSize:=BTSZ[cmBtsz];
      cmStpbs:=comStpBits.ItemIndex;
      Serial.StopBits:=STPBT[cmStpbs];
    end;
  end;
end;

function TOneRcdfram.startSerial:Boolean;
begin
  try
    Serial.StartComm;
    with showProgress do begin
      Left:=Round((RcdStringGrid.Width-Width)*0.5);
      Top:=Round((RcdStringGrid.Height-Height)*0.5);
      progBar.Position:=0;
      progressHint.Caption:='Transmitting data, please wait ... ...';
      Show;
    end;
    Result:=True;
  except
    Result:=False;
    Application.MessageBox('Start serial port error,please check your serial port settings','error',16);
  end;
end;

function TOneRcdfram.stopSerial:Boolean;
begin
  Serial.StopComm;
  Result:=True;
end;

function TOneRcdfram.saveRcd:Boolean;
var
  tmpRcd:TRcd;
  s:string;
  t:char;
  i,J:integer;
begin
  RealContrctCount:=0;
  with dbmodulefrm.dbtmpqry do begin
    active :=False;
    sql.Clear;
    sql.Add('Select * from CONTRACTOR ORDER BY URFID');
    execsql;
    active:=True;
    first;
    while not eof do begin
      ContrctArr[RealContrctCount].ID:=FieldByName('ID').Asinteger;
      ContrctArr[RealContrctCount].Name:=FieldByName('NAME').asstring;
      ContrctArr[RealContrctCount].LRFID:=FieldByName('LRFID').asstring;
      ContrctArr[RealContrctCount].URFID:=FieldByName('URFID').asstring;
      next;
      inc(RealContrctCount);
    end;
    Active:=False;
  end;
  with showProgress do begin
    Left:=Round((RcdStringGrid.Width-Width)*0.5);
    Top:=Round((RcdStringGrid.Height-Height)*0.5);
    progBar.Position:=0;
    progBar.Max:= RcdStringGrid.RowCount;
    progressHint.Caption:='System is saving data, please wait ... ...';
    Show;
  end;
  Exsleep(100);
  S:=ShortdateFormat;
  t:=DateSeparator;

  DateSeparator := '/';
  ShortdateFormat:='dd/mm/yyyy';
  dbmodulefrm.T_RCD.Active:=True;
  dbmodulefrm.T_EMPLOYEE.Active:=True;
  dbmodulefrm.T_PRODUCT.Active:=True;
  with RcdStringGrid do begin
    for i:=Save2MainDB to RowCount-2 do begin
      tmpRcd.ScaleID:=Cells[0,I];
      tmpRcd.DateTime:=strtoDatetime(Cells[1,I]+' '+Cells[2,I]);
      tmpRcd.RFID:=RightStr('0000000000'+Cells[3,I],10);
      val(Cells[4,I],tmpRcd.Trays,J);
      val(Cells[5,I],tmpRcd.NW,J);
      val(Cells[6,I],tmpRcd.GW,J);
      tmpRcd.ProductID:=Cells[7,I];
      val(Cells[8,I],tmpRcd.Penalty,J);
      val(Cells[9,I],tmpRcd.GQF,J);

      tmpRcd.ID:=RightStr(tmpRcd.RFID,5)+RightStr(Trim(tmpRcd.ScaleID),3)
                +FormatDateTime('yyMMddhhmmss',tmpRcd.DateTime);
      tmpRcd.TNW:=10000*tmpRcd.NW/(100-tmpRcd.Penalty)/(100-tmpRcd.GQF);
      tmpRcd.TGW:=tmpRcd.TNW+tmpRcd.GW-tmpRcd.NW;
      insert2DB(tmpRcd);
      UpdateRFID(tmpRcd.RFID);
      UpdatePRODUCT(tmpRcd.ProductID);
      progBar.Position:=I;
    end;
    Save2MainDB:=RowCount-1;
  end;
  ShortdateFormat:=S;
  DateSeparator:=t;
  showProgress.Hide;
  dbmodulefrm.T_EMPLOYEE.Active:=False;
  dbmodulefrm.T_RCD.Active:=False;
  dbmodulefrm.T_PRODUCT.Active:=False;
  dbmodulefrm.dealtmpRfid;
  dbmodulefrm.getcontractorlist(summaryfrm.ckContractor.Items);
  dbmodulefrm.getScaleID(summaryfrm.ckScaleID.Items);
  Result:=False;

end;

procedure TOneRcdfram.RcdStringGridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  vCol, vRow : LongInt;
  tW,tH:LongInt;
begin
  vCol := ACol; vRow := ARow;
  with Sender as TStringGrid, Canvas do begin
    tW:=(Rect.Right-Rect.Left-TextWidth(Cells[vCol, vRow])) div 2;
    tH:=(Rect.Bottom-Rect.Top-TextHeight('A')) div 2;
    FillRect(Rect);
    if vRow=0 then begin
      Font.Style :=Font.Style+[fsBold];
      TextRect(Rect, Rect.Left+tW, Rect.Top+tH, Cells[vCol, vRow]);
    end else
      TextRect(Rect, Rect.Left+tW, Rect.Top+tH, Cells[vCol, vRow]);
  end; 
end;

procedure TOneRcdfram.FilteCommData;
var
  BufSize,P:integer;
  frameStr,tmpCmd:string;
begin
  BufSize:=Length(FRcvBuff);

  if BufSize> MAX_FILE_SIZE then
    Delete(FRcvBuff,1,BufSize);

  P:=Pos(R_ED_FLG,FRcvBuff);

  if P<=0 then
    Exit;

  if (BufSize>p) then
    if R_ED_FLG=FRcvBuff[p+1] then
      P:=P+1;

  frameStr:=Copy(FRcvBuff, 1, p);
  delete(FRcvBuff, 1, p);
  tmpCmd:=frameStr[2]+frameStr[3];
  if SND_PREPARE=tmpCmd then
    SNDPREPARE(frameStr)
  else if SND_DATA=tmpCmd then
    EXSNDDATA(frameStr)
  else if SND_END=tmpCmd then
    SNDEND(frameStr);
end;

procedure TOneRcdfram.SndEnd(fstr:string);
begin
  Progbar.Position:=Progbar.Max;
  if IsRemoveMem then begin
    sndData('',RCV_CLEAR);
    sndData('',RCV_CLEAR);
  end else begin
    sndData('',RCV_OK);
    sndData('',RCV_OK);
  end;
  showProgress.Hide;
  FIsTran:=False;
  ExSleep(100);
  Serial.StopComm;
end;

procedure TOneRcdfram.SndPrepare(fstr:string);
var
  factStr:String;
begin
  factStr:=Copy(fstr,4,length(fstr)-4);
  Progbar.Max:=strtoint(factStr);
  sndData('',RCV_READY);
  FIsTran:=True;
end;

procedure TOneRcdfram.ExSndData(fstr:string);
var
  tmpStr,factStr:String;
  RcdCountInPage,I:DWORD;
  trays,p:Integer;
begin
  if StrCrc8(pByte(fstr),length(fstr)-1,tmpStr) then begin
    RcdCountInPage:=Strtoint(tmpStr[4]+tmpStr[5]);
    factStr:=Copy(tmpStr,6,length(tmpStr)-5);
    For I:=0 to RcdCountInPage-1 do begin
      with RcdStringGrid do begin
        Cells[0,RowCount-1]:=Copy(factStr,I*62+1,8);
        Cells[1,RowCount-1]:=Copy(factStr,I*62+9,10);
        Cells[2,RowCount-1]:=Copy(factStr,I*62+19,8);
        Cells[3,RowCount-1]:=Copy(factStr,I*62+27,10);
        val(Copy(factStr,I*62+37,1),trays,p);
        Cells[4,RowCount-1]:=inttostr(trays+1);
        Cells[5,RowCount-1]:=Copy(factStr,I*62+38,7);
        Cells[6,RowCount-1]:=Copy(factStr,I*62+45,7);
        Cells[7,RowCount-1]:=Copy(factStr,I*62+52,8);
        Cells[8,RowCount-1]:=Copy(factStr,I*62+60,2);
        Cells[9,RowCount-1]:=Copy(factStr,I*62+62,1);
        RowCount:=RowCount+1;
        RcdStringGrid.Row:=RowCount-1;
      end;
    end;
    Progbar.Position:=Progbar.Position+integer(RcdCountInPage);
    sndData('',RCV_RECEIVED);
  end else
    sndData('',RCV_AGAIN);
  OutTimer.Enabled:=True;
end;

procedure TOneRcdfram.sndData(data:String;cmd:String);
var
  SND_BUFF:PCHAR;
  tmp:string;
begin
  FSndLast_data:=data;
  FSndLast_Cmd:=cmd;
  tmp:=R_ST_FLG+cmd+data+R_ED_FLG;
  SND_BUFF:=pchar(tmp);
  Serial.WriteCommData(SND_BUFF,Length(tmp));
end;

procedure TOneRcdfram.SerialReceiveData(Sender: TObject; Buffer: Pointer;
  BufferLength: Word);
begin
  setLength(CurrBuff,BufferLength);
  CopyMemory(@CurrBuff[1],Buffer,BufferLength);
  FRcvBuff:=FRcvBuff+CurrBuff;
  FilteCommData;
end;

procedure TOneRcdfram.OutTimerTimer(Sender: TObject);
begin
  if not FIsTran then begin
    OutTimer.Enabled:=False;
    Exit;
  end;
  FWAITTIME:= FWAITTIME+OutTimer.Interval;
  if FWAITTIME<=MAX_WAIT_TIME then begin
    FTIMES:=0;
  end else begin
    FTIMES:=FTIMES+1;
    if FTIMES>=OVER_TIMES then begin
      FIsTran:=False;
      Application.MessageBox('Communication Time out, please close and restart','Time out',16);
    end;
    sndData(FSndLast_Data,FSndLast_Cmd);
    FWAITTIME:=0;
  end;
end;

end.
